/**
 * 
 */
package com.flashdeck.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang.math.RandomUtils;

/**
 * @author Vincentas
 *
 */
public class DeckProgress implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -9127766113816828614L;
	
	private final Set<String>[] groups;
	
	private String deckId;
	
	public DeckProgress(Set<Card> cards, String deckId, int groups) {
		if (groups < 2) {
			throw new Error("Atleast two groups are needed");
		}		
		
		if (cards.isEmpty()) {
			throw new Error("Atleast one card is needed");
		}
		
		this.groups = new Set[groups];
		
		for (int i = 0; i < groups; i++) {
			this.groups[i] = new HashSet<String>();
		}
		
		for (Card card : cards) {
			this.groups[0].add(card.getId());
		}
		
		this.deckId = deckId;
	}
	
	public int getGroups() {
		return groups.length;
	}
	
	public int getCardsInGroup(int group) {
		return groups[group].size();
	}
	
	private int findCardGroup(Card card) {
		for (int i = 0, n = groups.length; i < n; i++) {
			if (groups[i].contains(card.getId())){
				return i;
			}
		}
		
		throw new Error("Card not found " + card);
	}
	
	public void correctAnswer(Card card) {
		int cardGroup = findCardGroup(card);
		if (cardGroup < groups.length - 1) {
			groups[cardGroup].remove(card.getId());
			groups[cardGroup + 1].add(card.getId());
		}
	}
	
	public void incorrectAnswer(Card card) {
		int cardGroup = findCardGroup(card);
		if (cardGroup > 0) {
			groups[cardGroup].remove(card.getId());
			groups[0].add(card.getId());
		}
	}
	
	private int getNextGroup() {
		return RandomUtils.nextInt(groups.length);
	}
	
	public String getNextCardId() {
		String result = null;
		
		while (result == null) {
			int group = getNextGroup();
			if (!groups[group].isEmpty()) {				
				result = (String) groups[group].toArray()[RandomUtils.nextInt(groups[group].size())];
			}
		}
		
		return result;
	}
	
	/**
	 * @return the deckId
	 */
	public String getDeckId() {
		return deckId;
	}

	/**
	 * @param deckId the deckId to set
	 */
	public void setDeckId(String deckId) {
		this.deckId = deckId;
	}
	
	
}
